import Core.Gadget as Gadget
import Core.Algorithm as Algorithm
import Core.MongoDB as MongoDB
import pandas as pd
import numpy as np
import pymongo
from datetime import *

def LoadBarsAsDataFrame(symbol):
    barSeries = database.findWithFilter("Quote", symbol + "_Time_86400_Bar", filter, sort)

    fields = ['DateTime', 'BOpen', 'BHigh','BLow','BClose','Volume','Money']

    data = []
    for bar in barSeries:
        entry = []
        #entry.append(bar["StdDateTime"])
        entry.append(bar["DateTime"])
        entry.append(bar["Values"]["BOpen"])
        entry.append(bar["Values"]["BHigh"])
        entry.append(bar["Values"]["BLow"])
        entry.append(bar["Values"]["BClose"])
        entry.append(bar["Volume"])
        entry.append(bar["Money"])
        data.append(entry)

    df = pd.DataFrame(data, columns = fields)

    #print(df.head())
    #print(df[5-3+1:5])
    #df.iloc[5, 3] = np.nan
    #print(df)
    #print(df[df.isnull().values==True])
    #a = df.iloc[1]["BClose"]


    kkwood =1
    return df


def CheckMissing(dataFrame, err = "Missing Data"):
    a = dataFrame.isnull().any()
    for b in a:
        if b == True:
            print(err)
            break


#---2017-7-29 v2.0---
print("Chen's Quanlity Index")


database = MongoDB.MongoDB("192.168.1.100","27017")
sort = [("StdDateTime",pymongo.ASCENDING)]


#---instrument list---
instrumentList = database.findWithFilter("Instruments","InstrumentList",{"Symbol":"000300.SH"},sort)


#---Bara Cache---
barsCollectionBySymbol = {}


#---Hyper Parameters---
datetime1 = datetime(2010,1,1,15,0,0)
datetime2 = datetime(2015,1,1,0,0,0)
datetime1 = Gadget.ToUTCDateTime(datetime1)
datetime2 = Gadget.ToUTCDateTime(datetime2)
maxReferenceBars = 60
extremeToleranceDays = 5
index = -1

#---
filter = {}
filter["StdDateTime"] = {"$gt": datetime1, "$lt": datetime2}
bmBarSeries = database.findWithFilter("Quote","000300.SH_Time_86400_Bar",filter, sort)


#---Build Complete Dates---
data = []
for bar in bmBarSeries:
    entry = []
    entry.append(bar["DateTime"])
    data.append(entry)
dfBMSeries = pd.DataFrame(data, columns = ["DateTime"])
#print(dfBMSeries)

#---Main Loop, Loop Date---
length = len(dfBMSeries)
for index in range(maxReferenceBars-1, length): # 59~1200

    #---
    curDateTime = dfBMSeries.iloc[index]["DateTime"]
    curDateTime = Gadget.ParseDateTime(curDateTime)
    curDateTime = Gadget.ToUTCDateTime(curDateTime)

    #---Stat---
    sma20Count = 0
    sma60Count = 0
    breakout20Count = 0
    breakout60Count = 0

    #---Figuer out Instrument corresponding Date---
    instruments = Gadget.Find(instrumentList, curDateTime)

    #---Loop instruments---
    for instrument in instruments["Values"]:
        symbol = instrument["Symbol"]
        dfBarSeries = barsCollectionBySymbol.get(symbol)

        #---给每个Stock创建数据区（Sheet）---
        if dfBarSeries == None:
            #barSeries = database.findWithFilter("Quote", symbol + "_Time_86400_Bar", filter)
            dfBarSeries = LoadBarsAsDataFrame(symbol)
            dfBarSeries = pd.merge(dfBMSeries, dfBarSeries, on='DateTime', how='left')
            dfBarSeries["SMA20"] = 0
            dfBarSeries["SMA60"] = 0
            dfBarSeries["Breakout20"] = 0
            dfBarSeries["Breakout60"] = 0

            #---Checking Missing---
            dfMissing = dfBarSeries[dfBarSeries.isnull().values == True]
            if dfMissing.empty != True:
                print(dfMissing)
            barsCollectionBySymbol[symbol] = dfBarSeries


        #---Locate index---
        #barIndex = Gadget.FindIndex(barSeries, curDateTime)

        #---Calc Indicator---
        #---Moving Average---
        close = dfBarSeries.iloc[index]["BClose"]
        # [2:5] Get index 2,3,4(Not include 5), total 3
        closes = dfBarSeries[index - 20 + 1: index + 1]["BClose"]

        sma20 = np.mean(closes)
        if close > sma20:
            sma20Count += 1
            dfBarSeries.iloc[index]["SMA20"] = 1

        #
        closes = dfBarSeries[index - 60 + 1: index + 1]["BClose"]
        sma60 = np.mean(closes)
        if close > sma60:
            sma60Count += 1
            dfBarSeries.iloc[index]["SMA60"] = 1

        #New Hi
        closes = dfBarSeries[index - 20: index]["BClose"]
        hi20 = np.max(closes)
        if close > np.max(closes):
        #if hi20 < close:
            breakout20Count += 1
            dfBarSeries.iloc[index]["Breakout20"] = 1

        closes = dfBarSeries[index - 60: index]["BClose"]
        hi60 = np.max(closes)
        if close > hi60:
            breakout60Count += 1
            dfBarSeries.iloc[index]["Breakout60"] = 1

    kkwood = 0



#---V1.0 version Below---
for instrument in instruments:
    symbol = instrument.symbol
    #if symbol != "000543.SZ":
    #    continue
    #symbol = instrument[0]
    print("Load DataSeries " + symbol)

    barSeries = database.getDataSeries(symbol + "_Time_86400_Bar",datetime1,datetime2)
    barsCollectionBySymbol[symbol] = barSeries

last5DaysStatistcs = []
for i in range(extremeToleranceDays):
    last5DaysStatistcs.append([])

#Loop Days
for bar in bmBarSeries:
    index = index + 1
    if index < maxReferenceBars-1:
        continue

    newHi20s = []
    newLo20s = []
    sma20s = []
    sma60s = []
    valid20 = 0
    valid60 = 0
    curDateTime = bmBarSeries.getDateTime(index)
    datetime20DayBack = bmBarSeries.getDateTime(index - 19)
    datetime60DayBack = bmBarSeries.getDateTime(index - 59)
    print(str(curDateTime))
    for instrument in instruments:
        symbol = instrument.symbol
        barSeries = barsCollectionBySymbol[symbol]
        barIndex = barSeries.getIndex(curDateTime)
        barIndex20Back = barSeries.getIndex(datetime20DayBack)
        barIndex60Back = barSeries.getIndex(datetime60DayBack)
        if barIndex == None:
            print(symbol + " BarSeries Not has Data Before @ " + str(curDateTime))
        if barIndex20Back == None or barIndex -  barIndex20Back != 20 - 1:
            print(symbol + " BarSeries Too Less Data To Coverage 20" )
            continue
        valid20 = valid20 + 1

        close = barSeries[barIndex]["Values"]["BClose"]

        #20日新高或新低
        '''
        highest = Extreme(barSeries, barIndex-1, 20-1, True)
        lowest  = Extreme(barSeries, barIndex-1, 20-1, False)
        if close > highest:
            newHi20s.append(symbol)
        if close < lowest:
            newLo20s.append(symbol)
        '''
        #20 60MA
        sma20 = SMA(barSeries,barIndex,20)
        if close > sma20:
            sma20s.append(symbol)

        if barIndex60Back == None or barIndex -  barIndex60Back != 60 - 1:
            print(symbol + " BarSeries Too Less Data To Coverage 60" )
            continue
        valid60 = valid60 + 1

        sma60 = SMA(barSeries,barIndex,60)
        if close > sma60:
            sma60s.append(symbol)

        if Breakout(barSeries, barIndex, sma60, True):
            newHi20s.append(symbol)
        if Breakout(barSeries, barIndex, sma60, False):
            newLo20s.append(symbol)

        kkwood = 0

    # Calculate Last5days
    for j in range(extremeToleranceDays - 1 ):
        last5DaysStatistcs[j] = last5DaysStatistcs[j+1]
    last5DaysStatistcs[extremeToleranceDays -1] = [curDateTime,newHi20s,newLo20s ]

    newHi20sWthin5Days = []
    newLo20sWthin5Days = []
    for j in range(extremeToleranceDays):
        dailyStatistcs = last5DaysStatistcs[j]
        if dailyStatistcs.__len__() == 0:
            continue
        for symbol in dailyStatistcs[1]:
            if symbol not in newHi20sWthin5Days:
                newHi20sWthin5Days.append(symbol)
        for symbol in dailyStatistcs[2]:
            if symbol not in newLo20sWthin5Days:
                newLo20sWthin5Days.append(symbol)

    output = [curDateTime,valid20,valid60,
              newHi20s.__len__(),newHi20sWthin5Days.__len__(),
              newLo20s.__len__(),newLo20sWthin5Days.__len__(),
              sma20s.__len__(),sma60s.__len__(),
              ]
    print("Valid20 " + str(valid20) + " Valid60 " + str(valid60)
          + " NewHi " + str(newHi20s.__len__()) + " NewHi5Days " + str(newHi20sWthin5Days.__len__())
          + " NewLo " + str(newLo20s.__len__())  + " NewLo5Days " + str(newLo20sWthin5Days.__len__())
          + " SMA20 " + str(sma20s.__len__()) + " SMA60 " + str(sma60s.__len__())  )
    AppendListToFile("D:/ChenQuanlity.csv",output)

    kkwood = 1